/*
 * @Author: your name
 * @Date: 2021-04-13 10:12:31
 * @LastEditTime: 2021-04-13 12:01:36
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \学习笔记\TypeScript笔记\20模块系统.ts
 */
// 模块系统
// 模块术语变更
// "内部模块" 现在称作 "命名空间"; "外部模块" 现在则简称为 "模块"
// 模块在自身的作用域里执行，而不是在全局作用域里;
// 这意味着定义一个模块里的变量，函数，类等等在模块外部是不可见额，除非你明确地使用exprot形式之一到处他们。
// 相反,如果相适应其他模块熬出额变量,函数,类,接口等等地时后,你必须要导入他们,可以使用import形式之一.
// 模块是自声明地; 连个模块之间地挂你是通过在文件级别上使用import和export建立的.
// 如果一个文件不还有顶级import或export声明，那么它的内容被视为全局可见地（因此对模块也是可见的）

// 模块的导出
// 任何声明（比如变量，函数，类，类型别名或接口） 都能通过添加exprot关键字导出

// 模块的重新导出
// 我们经常会去拓展其他模块，并且只到处那个模块的部分内容，重新到处功能并不会在当前模块导入那个模块或定义一个新的局部变量
// 一个模块既可以引入也可以输出，甚至可以两者一起实现

import { userMsg } from './head'
export { userMsg }
// =>
// export {userMsg} from './head'

// 或者一个模块可以包裹多个模块，并把他们到处的内容联合在一起通过语法：export * from “module”
export * from './demo'
export * from './file'
export * from './head'
export * from './math'
export default {
    a: 1
}

// 默认导出
// 从前面的例子可以看出，使用import命令的时候，用户余姚知道所要加载的变量名和函数名，
// 否则无法加载，但是，用户肯定希望快速加载，未必愿意阅读文档，取料机模块有哪些属性和方法
// 为了给用户提供方便，让他们不要阅读文档就能加载模块，就要用到export default命令，为模块指定默认输出

// export defalut function () {
//     console.log('foo')
// }
// 上面代码是一个模块文件export-default.js ， 它的默认输出是一个函数

// import-default.js
// import customName from './export-default.js'
// customName();
// 其他模块加载该模块时，import命令可以为该匿名函数指定任意名字
// 上面代码的import命令，可以用任意名称指向export-default.js输出的方法
// 这时就不需要知道原模块输出额函数名
// 需要注意的是，这是important命令后面，不使用大括号

// export = 和 import = require()
// CommonJS 和 AMD 的环境里都有一个exports变量，这个变量包含了一个模块的所有导出内容
// CommonJS 和 AMD 的exports都可以被赋值为一个对象，这种情况下其作用就类似于 es6 语法里的默认到处，即 export default语法了。虽然作用相似，但是export default 语法并不能兼容 CommonJS 和 AMD 的exports

let numberRegexp = /^[0-9]+$/;
class ZipCodeValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }
}
export = ZipCodeValidator;

// 为了支持 CommonJS 和 AMD 的exports，typescript 提供了 export = 语法
// export = 语法定义一个模块的导出对象，这里的对象一词指的是类，接口，命名空间，函数或枚举
// 若使用exoprt = 导出一个模块，则必须使用TypeScript的特定语法import module = require("module")来导入此模块
import zip = require("./ZipCodeValidator");
let strings = ["hello", "98052", "101"];
let validator = new Zip();
strings.forEach(s => {
    console.log(`"${s}" - ${validator.isAcceptable(s) ? "matchs" : "does not match"}`);
})


// 生成模块代码

// 根据编译时指定的模块目标参数，编译器会生成相应的供 Node.js(CommonJS),Require.js(AMD),UMD,SystemJS 或 ECMAScript 2015 native modules(ES6)模块加载系统使用的代码

// AMD / RequireJS SimpleModule.js
define(["require","exports","./mod"],function (require,exports,modd_1)){
    exports.t = mod_1.something + 1;
}

// CommonJs / Node SimpleModule.js
let mod_1 = require("./mod");
export.t = mod_1.something + 1;
}

// Native ECMAScript 2015 modules SimpleModule.js
import { something } from "./mod";
export let t = something + 1;
}
// 为了编译，我们必须要在命令行上指定一个模块目标，对于Node.js来说，使用--module commonjs; 对于Require.js来说，使用--module amd

tsc --module commonjs Test.js
